package cn.cupster.floatwindowdemo

import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.app.Service
import android.content.Intent
import android.graphics.PixelFormat
import android.os.Binder
import android.os.Build
import android.os.IBinder
import android.util.DisplayMetrics
import android.util.Log
import android.view.*
import android.view.View.OnTouchListener
import android.view.animation.LinearInterpolator

/**
 *
 * @author HB.zyy酸菜鱼
 * @date 2021-08-13
 */
class FloatWindowServiceDragBind : Service() {

    companion object{
        private const val TAG = "FloatWindowServiceDrag"
        private const val INTENT_KEY_CONTENT = "WINDOW_CONTENT"
    }

    inner class WindowBinder : Binder(){
        fun obtainService()  =  this@FloatWindowServiceDragBind
    }

    private var mWindowManager: WindowManager? = null
    private var wmParams: WindowManager.LayoutParams? = null
    private var mView: View? = null

    //开始触控的坐标，移动时的坐标（相对于屏幕左上角的坐标）
    private var mTouchStartX = 0  //开始触控的坐标，移动时的坐标（相对于屏幕左上角的坐标）
    private var mTouchStartY = 0  //开始触控的坐标，移动时的坐标（相对于屏幕左上角的坐标）
    private var mTouchCurrentX = 0  //开始触控的坐标，移动时的坐标（相对于屏幕左上角的坐标）
    private var mTouchCurrentY = 0

    //开始时的坐标和结束时的坐标（相对于自身控件的坐标）
    private var mStartX = 0  //开始时的坐标和结束时的坐标（相对于自身控件的坐标）
    private var mStartY = 0  //开始时的坐标和结束时的坐标（相对于自身控件的坐标）
    private var mStopX = 0  //开始时的坐标和结束时的坐标（相对于自身控件的坐标）
    private var mStopY = 0

    //判断悬浮窗口是否移动，这里做个标记，防止移动后松手触发了点击事件
    private var isMove = false
    private var mValueAnimator: ValueAnimator? = null
    private var mImgMoveToEdgeAnim: ValueAnimator? = null

    private var mTouchSlop = 1
    private var screenHeight = 0
    private var screenWidth = 0

    private var mWindowText = ""

    override fun onCreate() {
        super.onCreate()
        mTouchSlop = ViewConfiguration.get(this).scaledTouchSlop
        mWindowManager = getSystemService(WINDOW_SERVICE) as WindowManager
        val dm = DisplayMetrics()
        mWindowManager?.defaultDisplay?.getMetrics(dm)
        screenWidth = dm.widthPixels
        screenHeight = dm.heightPixels
        initWindow()
        setUpTouch()
        AppApplication.boolOpenFloatWindow = true
    }

    override fun onBind(intent: Intent?): IBinder {
        intent?.let {
            val str = it.getStringExtra(INTENT_KEY_CONTENT)
            if (!str.isNullOrEmpty()){ mWindowText = str }
        }
        return WindowBinder()
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        return super.onStartCommand(intent, flags, startId)
    }

    override fun onUnbind(intent: Intent?): Boolean {
        return super.onUnbind(intent)
    }

    override fun onDestroy() {
        super.onDestroy()
        mValueAnimator?.apply { cancel() }
        mView?.let {
            mWindowManager?.removeView(mView)
        }
    }

    fun updateData(str : String){
        if (!str.isNullOrEmpty()){ mWindowText = str }
    }

    private fun initWindow() {
        wmParams = getParams()
        mView = LayoutInflater.from(this).inflate(R.layout.float_window_layout ,null ,false)
        // 添加悬浮窗的视图
        mWindowManager!!.addView(mView, wmParams)
        mView?.setOnClickListener {
            Log.e(TAG, "initWindow: click root" )
        }
        mView?.findViewById<View>(R.id.btnClose)?.setOnClickListener {
            AppApplication.boolOpenFloatWindow = false
            stopSelf()//bind方式启动的话 ，使用unbind方式解绑
        }
    }

    private fun getParams(): WindowManager.LayoutParams? {
        wmParams = WindowManager.LayoutParams()
        // 悬浮窗默认显示以左上角为起始坐标
        // 悬浮窗默认显示以左上角为起始坐标
        wmParams!!.gravity = Gravity.RIGHT or Gravity.BOTTOM
        //设置window type 下面变量2002是在屏幕区域显示，2003则可以显示在状态栏之上
        when {
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
                wmParams!!.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
            }
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1 -> {
                wmParams!!.type = WindowManager.LayoutParams.TYPE_PHONE
            }
            else -> {
                wmParams!!.type = WindowManager.LayoutParams.TYPE_TOAST
            }
        }
        wmParams!!.flags =
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
                    WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR or
                    WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
        //设置悬浮窗口长宽数据
        wmParams!!.width = WindowManager.LayoutParams.WRAP_CONTENT
        wmParams!!.height = WindowManager.LayoutParams.WRAP_CONTENT
        wmParams!!.format = PixelFormat.RGBA_8888
        return wmParams
    }

    @SuppressLint("ClickableViewAccessibility")
    private fun setUpTouch(){
        mView?.setOnTouchListener(object : OnTouchListener{
            override fun onTouch(v: View, event: MotionEvent): Boolean {
                wmParams?.let { param ->
                    when (event.action) {
                        MotionEvent.ACTION_DOWN -> {
                            isMove = false
                            mTouchStartX = event.rawX.toInt()
                            mTouchStartY = event.rawY.toInt()
                            mStartX = event.rawX.toInt()
                            mStartY = event.rawY.toInt()
                        }
                        MotionEvent.ACTION_MOVE -> {
                            mTouchCurrentX = event.rawX.toInt()
                            mTouchCurrentY = event.rawY.toInt()
                            param.x += mTouchStartX - mTouchCurrentX
                            param.y += mTouchStartY - mTouchCurrentY
                            mWindowManager?.updateViewLayout(mView, wmParams)
                            mTouchStartX = mTouchCurrentX
                            mTouchStartY = mTouchCurrentY
                        }
                        MotionEvent.ACTION_UP -> {
                            mStopX = event.rawX.toInt()
                            mStopY = event.rawY.toInt()
                            if (Math.abs(mStartX - mStopX) >= mTouchSlop || Math.abs(mStartY - mStopY) >= mTouchSlop) {
                                isMove = true
                                if (param.x < screenWidth / 2 - mView!!.measuredWidth / 2
                                ) {
                                    moveSmallImageToEdge(0)
                                } else {
                                    moveSmallImageToEdge(
                                        screenWidth - mView!!.measuredWidth
                                    )
                                }
                            }
                        }
                        else -> {
                        }
                    }
                }
                //如果是移动事件不触发OnClick事件，防止移动的时候一放手形成点击事件
                return isMove
            }
        })
    }

    private fun moveSmallImageToEdge(desX: Int) {
        if (mImgMoveToEdgeAnim?.isRunning == true) {
            mImgMoveToEdgeAnim!!.cancel()
        }
        mImgMoveToEdgeAnim = ValueAnimator.ofInt(wmParams!!.x, desX).apply {
            duration = 200
            interpolator = LinearInterpolator()
            addUpdateListener { animation ->
                wmParams!!.x = animation.animatedValue as Int
                try {
                    mWindowManager!!.updateViewLayout(mView, wmParams)
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        }
        mImgMoveToEdgeAnim?.start()
    }



}